package fem2d;

import fem2.AbstractStructuralStaticDemo;
import fem2.Constraint;
import fem2.Debugger;
import fem2.Element;
import fem2.MaterialModel;
import fem2.Mesh;
import fem2.MeshPart;
import fem2.MeshUtilities;
import fem2.Model;
import fem2.Observer;
import fem2.analysis.Analysis;
import fem2.analysis.NonlinearStaticAnalysis;
import fem2.element.StructuralElement;
import fem2.enu.EchoLevelType;
import fem2.enu.State;
import fem2.material.ExponentialSofteningRule;
import fem2.material.FluencyCriteria;
import fem2.material.IsotropicDamageMMimplex;
import fem2.observer.GidDamageObserver;
import fem2.observer.TimeStepObserver;
import fem2.strategies.Strategy;

public class LshapeIsotropicDamage extends AbstractStructuralStaticDemo {

	public LshapeIsotropicDamage() {
		projectDir = "/home/hbui/kratos_janosch";
		projectName = "LshapeIsotropicDamage.gid";
		meshFileName = "structured_mesh.msh";
	}

	@Override
	public Mesh createMesh() {
		return new Lshape().createMesh();
	}

	@Override
	public Model createConditions(Model m) {
		Mesh mesh = m.getMesh();
		Constraint c1 = new Constraint(false, false);
		Constraint c2 = new Constraint(true, false);
		// c2.setValue(1, -0.2);
		// c2.setValue(1, -1.0);
		c2.setValue(1, -10.0);
		mesh.setConstraint(c1, MeshUtilities.seekNodesOnSurface(mesh, 0, 1, -1000));
		MeshUtilities.seekNode(mesh, 1000, 500).setConstraint(c2);
		return m;
	}

	@Override
	public MaterialModel createMaterial(Model m) {
		double E = 25850;
		double nu = 0.18;
		double t = 200;
		double ft = 2.7;
		// double Gf = 0.065;
		double e0 = ft / Math.sqrt(E);
		// double ef = Gf / ft;
		double ef = 1e2 * e0;
		FluencyCriteria softeningRule = new ExponentialSofteningRule(e0, ef);

		return new IsotropicDamageMMimplex(E, nu, 0, t, State.PLANE_STRAIN, softeningRule, e0);

		// return new IsotropicDamageMM(E, nu, 0, t, State.PLANE_STRAIN,
		// softeningRule, e0);
		// work with very small stepping (1e-3) and localize at the tip

		// return new IsotropicDamageMM(E, nu, 0, t, State.PLANE_STRESS,
		// softeningRule, e0); //may work with very small stepping as above
	}

	@Override
	public Element createElement(MeshPart mp, MaterialModel mm) {
		Element e = new StructuralElement(mp, mm);
		e.setEchoLevel(EchoLevelType.AUX4);
		return e;
	}

	@Override
	public void addObservers(Model m, Strategy s, TimeStepObserver o) {
		super.addObservers(m, s, o);

		if (meshFileName == null) {
			throw new Error("mesh file name was not set");
		}

		/*
		 * clean all previous post files
		 */
		String meshName = meshFileName.split("\\.")[0];

		Observer do1 = new GidDamageObserver(m, o, projectDir, projectName, meshName);
		s.addObserver(do1);

	}

	@Override
	public void run(int nt) {
		Model m = createModel();

		Analysis an = new NonlinearStaticAnalysis(m, nt);
		Strategy s = an.getStrategy();
		s.setEchoLevel(EchoLevelType.OUTPUT, EchoLevelType.AUX1);
		// ((NewtonRaphsonStrategy) s)
		// .setLineSearchCriteria(LineSearchCriteria.INTERPOLATED_LINE_SEARCH);

		addObservers(m, s, new TimeStepObserver(s));

		an.run();

		// postProcess(m);

		Debugger.warn("Analysis completed");
	}

	public static void main(String[] args) {
		AbstractStructuralStaticDemo demo = new LshapeIsotropicDamage();

		// demo.run(10); //for du = -0.2
		// demo.run(40);
		demo.run(1000);

	}
}
